﻿using System;
using System.Collections.ObjectModel;
using SCG = System.Collections.Generic;

using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using GASS.OpenCL;
using GASS.OpenCL.OpenCLDriver;

namespace Nemerle.OpenCL {

    [InfoProperty(CLPlatformInfo.Profile, string)]
    [InfoProperty(CLPlatformInfo.Version, string)]
    [InfoProperty(CLPlatformInfo.Name, string)]
    [InfoProperty(CLPlatformInfo.Vender, string, Name = Vendor)]
    [InfoProperty(CLPlatformInfo.Extensions, ReadOnlyCollection.[string])]
    [EqualityByIdPattern]
    public sealed class Platform {

        public static DefaultPlatform : Platform {
            platform : LazyValue[Platform] = lazy(
                match(buffered clGetPlatformIDs()) {
                    | ids when ids.Length > 0 => Platform(ids[0])
                    | _ => null
                }
            );
            get { platform.Value }
        }

        public static GetPlatforms() : array[Platform] {
            Array.ConvertAll(buffered clGetPlatformIDs(), Platform(_));
        }

        private this(id : CLPlatformID) {
            this.id = id;
        }

        [Accessor] id : CLPlatformID;

        public GetDevice(device_type : CLDeviceType) : Device {
            match(GetDevices(device_type)) {
                | devices when devices.Length > 0 => devices[0]
                | _ => null
            }
        }

        public GetDevices(device_type : CLDeviceType) : array[Device] {
            try {
                Array.ConvertAll(buffered clGetDeviceIDs(id, device_type), Device(this, _))
            } catch {
                | e is OpenCLException when e.Code == CLError.DeviceNotFound => array(0)
            }
        }

        public override ToString() : string {
            Name
        }

    }
  
}
